package org.enhance.common.model.po;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import org.apache.commons.collections4.CollectionUtils;
import org.enhance.common.util.Assertion;

import lombok.Getter;
import lombok.Setter;

@Getter
@Setter
public class GeoPolygon extends AbstractGeo {

	private static final long serialVersionUID = 1937295214272363107L;

	private List<GeoPoint> geoPoints;

	public GeoPolygon addGeoPoint(BigDecimal longitude, BigDecimal latitude) {
		GeoPoint geoPoint = new GeoPoint(longitude, latitude);
		addGeoPoint(geoPoint);
		return this;
	}

	public GeoPolygon addGeoPoint(BigDecimal longitude, BigDecimal latitude, BigDecimal altitude) {
		GeoPoint geoPoint = new GeoPoint(longitude, latitude, altitude);
		addGeoPoint(geoPoint);
		return this;
	}

	public GeoPolygon addGeoPoint(GeoPoint geoPoint) {
		if (null != geoPoint) {
			if (null == geoPoints) {
				geoPoints = new ArrayList<>();
			}
			geoPoints.add(geoPoint);
		}
		return this;
	}

	@Override
	public boolean equals(Object o) {
		if (this == o) {
			return true;
		}
		if (o == null || getClass() != o.getClass()) {
			return false;
		}
		GeoPolygon that = (GeoPolygon) o;
		return geoPoints.equals(that.geoPoints);
	}

	@Override
	public int hashCode() {
		return Objects.hash(geoPoints);
	}

	@Override
	public String generateShape() {
		if (!geoPoints.isEmpty()) {
			Assertion.isTrue(isPolygon(), "地块数据有问题，请检查");
			StringBuilder sb = new StringBuilder("POLYGON((");
			for (int i = 0; i < geoPoints.size(); i++) {
				GeoPoint geoPoint = geoPoints.get(i);
				sb.append(geoPoint.getLongitude()).append(" ").append(geoPoint.getLatitude());
				if (geoPoint.getAltitude() != null) {
					sb.append(" ").append(geoPoint.getAltitude());
				}
				if (i != geoPoints.size() - 1) {
					sb.append(",");
				}
			}
			sb.append("))");
			return sb.toString();
		}
		return null;
	}

	public boolean isPolygon() {
		return CollectionUtils.isNotEmpty(geoPoints) && geoPoints.size() >= 4 && geoPoints.get(0).equals(geoPoints.get(geoPoints.size() - 1));
	}
}
